


class ModelBase(type):
    """所有模型的元类"""

    def __new__(cls, name, bases, attrs, **kwargs):
        super_new = super().__new__

        # 只对Model的子类执行初始化（排除Model类本身）
        parents = [b for b in bases if isinstance(b, ModelBase)]
        if not parents:
            return super_new(cls, name, bases, attrs)

        # 创建新类
        module = attrs.pop("__module__")
        new_attrs = {"__module__": module}
        classcell = attrs.pop("__classcell__", None)

        if classcell is not None:
            new_attrs["__classcell__"] = classcell

        attr_meta = attrs.pop("Meta", None)
        # 将没有contribute_to_class()方法的属性传递给type.__new__()
        contributable_attrs = {}
        for obj_name, obj in attrs.items():
            if _has_contribute_to_class(obj):
                contributable_attrs[obj_name] = obj
            else:
                new_attrs[obj_name] = obj

        new_class = super_new(cls, name, bases, new_attrs, **kwargs)

        abstract = getattr(attr_meta, "abstract", False)
        meta = attr_meta or getattr(new_class, "Meta", None)
        base_meta = getattr(new_class, "_meta", None)

        app_label = None

        # 查找包含该模型的应用程序配置
        app_config = apps.get_containing_app_config(module)

        if getattr(meta, "app_label", None) is None:
            if app_config is None:
                if not abstract:
                    raise RuntimeError(
                        "模型类 %s.%s 没有显式声明app_label "
                        "且不在INSTALLED_APPS的任何应用中" % (module, name)
                    )
            else:
                app_label = app_config.label

        # 添加_meta属性
        new_class.add_to_class("_meta", Options(meta, app_label))
        if not abstract:
            # 添加DoesNotExist异常类
            new_class.add_to_class(
                "DoesNotExist",
                subclass_exception(
                    "DoesNotExist",
                    tuple(
                        x.DoesNotExist
                        for x in parents
                        if hasattr(x, "_meta") and not x._meta.abstract
                    )
                    or (ObjectDoesNotExist,),
                    module,
                    attached_to=new_class,
                ),
            )
            # 添加MultipleObjectsReturned异常类
            new_class.add_to_class(
                "MultipleObjectsReturned",
                subclass_exception(
                    "MultipleObjectsReturned",
                    tuple(
                        x.MultipleObjectsReturned
                        for x in parents
                        if hasattr(x, "_meta") and not x._meta.abstract
                    )
                    or (MultipleObjectsReturned,),
                    module,
                    attached_to=new_class,
                ),
            )
            # 从非抽象父类继承某些属性
            if base_meta and not base_meta.abstract:
                if not hasattr(meta, "ordering"):
                    new_class._meta.ordering = base_meta.ordering
                if not hasattr(meta, "get_latest_by"):
                    new_class._meta.get_latest_by = base_meta.get_latest_by

        is_proxy = new_class._meta.proxy

        # 如果是代理模型，确保基类未被替换
        if is_proxy and base_meta and base_meta.swapped:
            raise TypeError("%s 不能代理被替换的模型 '%s'." % (name, base_meta.swapped))

        # 添加具有contribute_to_class()方法的剩余属性
        for obj_name, obj in contributable_attrs.items():
            new_class.add_to_class(obj_name, obj)

        # 收集所有字段名称
        new_fields = chain(
            new_class._meta.local_fields,
            new_class._meta.local_many_to_many,
            new_class._meta.private_fields,
        )
        field_names = {f.name for f in new_fields}

        # 代理模型的基本设置
        if is_proxy:
            base = None
            for parent in [kls for kls in parents if hasattr(kls, "_meta")]:
                if parent._meta.abstract:
                    if parent._meta.fields:
                        raise TypeError(
                            "抽象基类包含模型字段不允许用于代理模型 '%s'." % name
                        )
                    else:
                        continue
                if base is None:
                    base = parent
                elif parent._meta.concrete_model is not base._meta.concrete_model:
                    raise TypeError("代理模型 '%s' 有多个非抽象模型基类." % name)
            if base is None:
                raise TypeError("代理模型 '%s' 没有非抽象模型基类." % name)
            new_class._meta.setup_proxy(base)
            new_class._meta.concrete_model = base._meta.concrete_model
        else:
            new_class._meta.concrete_model = new_class

        # 收集多表继承的父链接
        parent_links = {}
        for base in reversed([new_class] + parents):
            if not hasattr(base, "_meta"):
                continue
            if base != new_class and not base._meta.abstract:
                continue
            # 定位OneToOneField实例
            for field in base._meta.local_fields:
                if isinstance(field, OneToOneField) and field.remote_field.parent_link:
                    related = resolve_relation(new_class, field.remote_field.model)
                    parent_links[make_model_tuple(related)] = field

        # 跟踪从基类继承的字段
        inherited_attributes = set()
        # 为所有模型父类执行适当的设置
        for base in new_class.mro():
            if base not in parents or not hasattr(base, "_meta"):
                inherited_attributes.update(base.__dict__)
                continue

            parent_fields = base._meta.local_fields + base._meta.local_many_to_many
            if not base._meta.abstract:
                # 检查本地声明字段与基类字段的冲突
                for field in parent_fields:
                    if field.name in field_names:
                        raise FieldError(
                            "类 %r 中的本地字段 %r 与基类 %r 的同名字段冲突."
                            % (field.name, name, base.__name__)
                        )
                    else:
                        inherited_attributes.add(field.name)

                # 具体类处理...
                base = base._meta.concrete_model
                base_key = make_model_tuple(base)
                if base_key in parent_links:
                    field = parent_links[base_key]
                elif not is_proxy:
                    # 自动创建父链接字段
                    attr_name = "%s_ptr" % base._meta.model_name
                    field = OneToOneField(
                        base,
                        on_delete=CASCADE,
                        name=attr_name,
                        auto_created=True,
                        parent_link=True,
                    )

                    if attr_name in field_names:
                        raise FieldError(
                            "类 %r 中自动生成的字段 '%s' 与基类 %r 的同名字段冲突."
                            % (name, attr_name, base.__name__)
                        )

                    if not hasattr(new_class, attr_name):
                        new_class.add_to_class(attr_name, field)
                else:
                    field = None
                new_class._meta.parents[base] = field
            else:
                # 处理抽象基类
                base_parents = base._meta.parents.copy()

                # 添加未被覆盖的抽象基类字段
                for field in parent_fields:
                    if (
                        field.name not in field_names
                        and field.name not in new_class.__dict__
                        and field.name not in inherited_attributes
                    ):
                        new_field = copy.deepcopy(field)
                        new_class.add_to_class(field.name, new_field)
                        # 用新字段替换此基类上定义的父链接
                        if field.one_to_one:
                            for parent, parent_link in base_parents.items():
                                if field == parent_link:
                                    base_parents[parent] = new_field

                new_class._meta.parents.update(base_parents)

            # 从父类继承私有字段（如GenericForeignKey）
            for field in base._meta.private_fields:
                if field.name in field_names:
                    if not base._meta.abstract:
                        raise FieldError(
                            "类 %r 中的本地字段 %r 与基类 %r 的同名字段冲突."
                            % (field.name, name, base.__name__)
                        )
                else:
                    field = copy.deepcopy(field)
                    if not base._meta.abstract:
                        field.mti_inherited = True
                    new_class.add_to_class(field.name, field)

        # 复制索引以确保模型扩展抽象模型时索引名称唯一
        new_class._meta.indexes = [
            copy.deepcopy(idx) for idx in new_class._meta.indexes
        ]

        if abstract:
            # 抽象基模型的特殊处理
            attr_meta.abstract = False
            new_class.Meta = attr_meta
            return new_class

        # 准备模型并注册
        new_class._prepare()
        new_class._meta.apps.register_model(new_class._meta.app_label, new_class)
        return new_class